using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Threading;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net;
using System.Data.OleDb;
using System.IO;
using Sanford.Multimedia.Midi;

namespace NetMonitor.Things
{

    public abstract class Thing
    {
        private OutputDevice outDevice;
        NetworkMap networkMap;
        public int x, y, w, h;
        public int id = -1;
        
        public int interval = 10000, max = 100;
        public string hostname = "", alias = "", classDescription = "", thingDescription = "";
        public int historySize = 20;
        public int timeOut = 2000;
        public int midiProgram = 11;
        public int parentThingId;

        public Color col;
        public bool selected = false;
        protected Font font;
        
        int handleSize = 8;
        protected List<int> history;
        
        protected float boxX, boxY, boxW, boxH;
        protected Color boxColor = Color.Black;
        public int lastRunTime = 0;
        public bool queued = false;

        protected FileStream fileStream;

        protected Thing()
        {
            
            history = new List<int>();
            hostname = "rov";
            font = new Font("Arial", 14);
            col = Color.Green;
            init();
        }

         ~Thing()
        {
            fileStream.Close(); 
        }

        public void setNetworkMap(NetworkMap _map)
        {
            networkMap = _map;
        }

        public void setSound(OutputDevice _outDevice)
        {
            outDevice = _outDevice;
        }

        protected virtual void init() { }

      /*  protected DataTable getHistory()
        {
            string str_select = "SELECT TOP " + historySize.ToString() + " Val FROM tblHistory WHERE Thing = " + id.ToString() + " ORDER BY Time DESC";
            OleDbConnection con = new OleDbConnection(constr);
            DataSet ds = new DataSet();
            OleDbDataAdapter da = new OleDbDataAdapter(str_select, con);

            da.Fill(ds);
            return ds.Tables[0];
        }*/

        public void note( int note)
        {
            networkMap.sound.noteOn((byte)lastValue());
           /* if (lastValue() > 8 && lastValue() < 127)
            {             
                outDevice.Send(new ChannelMessage(ChannelCommand.NoteOff, 0, lastValue(), 127));
            }

            if (note > 8 && note < 127)
            {
                outDevice.Send(new ChannelMessage(ChannelCommand.ProgramChange, 0, midiProgram));
                outDevice.Send(new ChannelMessage(ChannelCommand.NoteOn, 0, note, 127));
            }*/
        }

        private void drawCenteredBox(Graphics g, float x, float y, float w, float h, string s)
        {
            Pen pen = new Pen(col);

            pen.EndCap = LineCap.Flat;

            pen.Width = 1;

            g.FillRectangle(new SolidBrush(Color.White), x - w / 2, y - h / 2, w, h);
            g.DrawRectangle(pen, x - w / 2, y - h / 2, w, h);
            if (s != "")
                g.DrawString(s, font, new SolidBrush(col), new PointF(x - w / 2, y - h / 2));
        }

        public void draw(Graphics g )
        {
            drawThing(g);

            if (selected)
            { // draw handles
                drawCenteredBox(g, x, y, handleSize, handleSize, "");
                drawCenteredBox(g, x + w, y + h, handleSize, handleSize, "");
            }
            if (boxColor == Color.Yellow)
                boxColor = Color.Black;
        }

        public abstract void drawThing(Graphics g);

        private bool clickHandle(float _x, float _y, float _x2, float _y2)
        {
            if (_x > _x2 - handleSize / 2 && _x < _x2 + handleSize / 2 &&
                _y > _y2 - handleSize / 2 && _y < _y2 + handleSize / 2)
                return true;
            return false;
        }

        public int validateClick(float _x, float _y)
        {
            if (_x > boxX && _x < boxX + boxW &&
                _y > boxY && _y < boxY + boxH)
                return 1;

            if (clickHandle(_x, _y, x, y))
                return 2;

            if (clickHandle(_x, _y, x + w, y + h))
                return 3;

            return 0;
        }


        protected string getText()
        {
            if (alias != "")
                return alias;
            return hostname;
        }

        protected abstract int ping();

        public void pingerThreadFunc(Object threadContext)
        {    
            try
            {
                lastRunTime = Environment.TickCount & Int32.MaxValue; // ms since app start (cycles every 24 days)
                
                boxColor = Color.Yellow;

                int iReply = -12;
                try
                {
                    iReply = ping();
                    add(iReply);
                }
                catch (Exception ex)
                {
                    add(-17);
                    ex.ToString();
                }

                if (iReply < max && iReply >= 0)
                    col = Color.Green;
                else
                    if (
                         (history.Count > 0 && (history[history.Count - 1] >= max || history[history.Count - 1] < 0)) &&
                         (history.Count > 1 && (history[history.Count - 2] >= max || history[history.Count - 2] < 0))
                        )
                    {
                        col = Color.Red;
                    }
                    else
                        col = Color.Orange;           
            }
            catch (Exception ex)
            {
                ex.ToString();
            }
            queued = false;
        }

        private int add(int _val)
        {
            note(_val);
            history.Add(_val);
            while (history.Count > historySize)
                history.RemoveAt(0);

            //if (networkMap.LogToDb)
            {
                if (fileStream == null || !fileStream.CanWrite)
                    fileStream = File.Open(id.ToString() + ".dat", FileMode.Append);
                BinaryWriter bw = new BinaryWriter(fileStream);
                bw.Write(DateTime.Now.Ticks);
                bw.Write(_val);
                bw.Close();
                              
            }
            return _val;
        }

        public int lastValue()
        {
            if (history.Count > 0)
                return history[history.Count - 1];
            else return 0;
        }



       

    }
}
